<template>
  <div class="widget-view">
    <div class="widget-sticky" style="position: sticky; top: 0; z-index: 99; background-color: #fff">
      <div class="tip-usage d-flex px-8 py-5 fs-xs">
        <SvgIcon class-name="mr-4 flex-shrink-0" icon-class="warn"></SvgIcon>使用提示：拖拽组件进入页面即可
      </div>
      <!-- toggle -->
      <div class="d-flex">
        <div
          class="widget-group-toggle flex-1 t-center"
          :class="{ active: activeWidgetGroup === 'Finance' }"
          @click="activeWidgetGroup = 'Finance'"
        >
          模板组件
        </div>
        <div
          class="widget-group-toggle flex-1 t-center"
          :class="{ active: activeWidgetGroup === 'Basic' }"
          @click="activeWidgetGroup = 'Basic'"
        >
          通用组件
        </div>
      </div>
      <!-- 基金组件内容 -->
      <!-- <div v-if="activeWidgetGroup === 'Finance' && isH5" class="d-flex al-center jc-between mt-24 px-24"> -->
      <!-- <div class="d-flex jc-between flex-1 pr-12"> -->
      <!-- <div
            v-for="keyword in financeKeywordCollapse"
            :key="keyword"
            class="pointer"
            :class="keyword === activeFinanceKeyword ? 't-theme' : 't-grey'"
            @click="activeFinanceKeyword = keyword"
          >
            <span>{{ keyword }}</span>
          </div> -->
      <!-- </div> -->
      <!-- <el-dropdown @visible-change="(visible) => (dropdownIn = visible)">
          <div class="keyword-dropdown-toggle d-flex jc-between al-center t-dark pointer">
            <i class="icon icon-more mr-4"></i>
            <span>{{ activeFinanceKeyword }}</span>
            <i class="icon icon-arrow-dark ml-4" :class="{ 'dropdown-in': dropdownIn }"></i>
          </div>
          <el-dropdown-menu slot="dropdown" class="keyword-dropdown-menu p-24">
            <div
              v-for="keyword in ['全部', ...financeKeywordCollapse]"
              :key="keyword"
              class="keyword"
              :class="{ 't-theme': keyword === activeFinanceKeyword }"
              @click="activeFinanceKeyword = keyword"
            >
              {{ keyword }}
            </div>
          </el-dropdown-menu>
        </el-dropdown> -->
    </div>
    <!-- </div> -->

    <el-collapse
      v-show="activeWidgetGroup === 'Finance'"
      v-model="financeKeywordCollapse"
      class="mt-12 px-24"
      style="position: relative"
    >
      <template v-for="keyword in financeKeywordCollapse">
        <el-collapse-item v-if="['全部', keyword].includes(activeFinanceKeyword)" :key="keyword" :name="keyword">
          <template #title>{{ keyword }}</template>
          <div class="widget-list" @drop.prevent.stop>
            <vuedraggable
              :list="filterKeywordWidget(keyword, 'Finance')"
              :sort="false"
              :group="{ name: 'Widgets', pull: 'clone', put: false }"
              :clone="onDragClone"
              class="d-flex flex-wrap jc-between pt-16"
              @dragend.native.prevent="onDragEnter"
            >
              <div
                v-for="(widget, i) in filterKeywordWidget(keyword, 'Finance')"
                :id="i === 0 && 'first-widget'"
                :key="widget.cId"
                class="widget-item"
              >
                <div class="layer d-flex jc-center al-center">
                  <img class="mini-pic" draggable="false" :src="_calcWidgetCoverImageUrl('Finance', widget, keyword)" />
                </div>
                <div class="t-center mt-16">{{ widget.label }}</div>
              </div>
            </vuedraggable>
          </div>
        </el-collapse-item>
      </template>
    </el-collapse>
    <!-- 通用组件内容 -->
    <el-collapse
      v-show="activeWidgetGroup === 'Basic'"
      v-model="basicKeywordCollapse"
      class="mt-6 px-24"
      style="position: relative"
    >
      <el-collapse-item v-for="keyword in basicKeywordCollapse" :key="keyword" :name="keyword">
        <template #title>{{ keyword }}</template>
        <div class="basic-widget-list widget-list" @drop.prevent.stop>
          <vuedraggable
            :list="filterKeywordWidget(keyword, 'Basic')"
            :sort="false"
            :group="{ name: 'Widgets', pull: 'clone', put: false }"
            :clone="onDragClone"
            class="d-flex flex-wrap jc-between pt-16"
            @dragend.native.prevent="onDragEnter"
          >
            <div v-for="widget in filterKeywordWidget(keyword, 'Basic')" :key="widget.cId" class="widget-item">
              <div class="layer d-flex jc-center al-center">
                <img class="mini-pic" draggable="false" :src="_calcWidgetCoverImageUrl('Basic', widget, keyword)" />
                <div v-if="isSuper(widget, 'Basic', keyword)" class="super">专属</div>
              </div>
              <div class="t-center mt-16">{{ widget.label }}</div>
            </div>
          </vuedraggable>
        </div>
      </el-collapse-item>
    </el-collapse>
    <!-- 弹窗 -->
    <UploadWidgetDialog @uploaded="getSystemWidgetList" />
  </div>
</template>

<script>
  import { mapGetters, mapMutations } from 'vuex';
  import { deepClone, generateID } from '@/utils';
  import vuedraggable from 'vuedraggable';
  import UploadWidgetDialog from './UploadWidgetDialog.vue';
  import { h5KeywordWidgetMap, basicKeywordWidgetMap } from './setting';
  import { basicWidgets, h5Widgets } from '../../landingPageWidget/widget-list';

  export default {
    components: { vuedraggable, UploadWidgetDialog },
    data() {
      return {
        activeWidgetGroup: 'Finance',
        activeFinanceKeyword: '全部',
        // 远程系统组件
        remoteSystemWidgetList: { Finance: {}, Basic: {} },
        remoteSystemWidgetData: null,
        dropdownIn: false
      };
    },
    inject: ['isH5'],
    computed: {
      ...mapGetters('component', ['previewer', 'componentData', 'zIndexMax', 'scaleRatio']),
      widgetList() {
        return basicWidgets.concat(h5Widgets);
      },
      basicKeywordWidgetMap() {
        const keywordWidgetMap = new Map([...basicKeywordWidgetMap]);
        if (!this.isH5) keywordWidgetMap.delete('视频');
        return keywordWidgetMap;
      },
      financeKeywordWidgetMap() {
        return h5KeywordWidgetMap;
      },
      financeKeywordCollapse: {
        set: (arr) => arr,
        get() {
          return Array.from(this.financeKeywordWidgetMap.keys());
        }
      },
      basicKeywordCollapse: {
        set: (arr) => arr,
        get() {
          return Array.from(this.basicKeywordWidgetMap.keys());
        }
      }
    },
    mounted() {},
    methods: {
      ...mapMutations('component', ['ADD_COMPONENT']),

      // 是否为定制组件
      isSuper(widget, group, keyword) {
        const keywordMap = group === 'Finance' ? this.financeKeywordWidgetMap : this.basicKeywordWidgetMap;
        const component = keywordMap
          .get(keyword)
          .find((component) => widget.component === component || widget.component === component.name);
        return component?.include;
      },

      // 筛选组件 by keyword （由远程系统组件 + 本地组件 计算结果）
      filterKeywordWidget(keyword, group) {
        // keyword 组件二级分类关键词 group 组件一级分类(金融/基础组件)
        const keywordMap = group === 'Finance' ? this.financeKeywordWidgetMap : this.basicKeywordWidgetMap;
        // 过滤本地组件列表
        const localWidgetList = keywordMap.get(keyword).reduce((list, item) => {
          if (item instanceof Object) {
            list.push(item.name);
            return list;
          }
          list.push(item);
          return list;
        }, []);

        // 远程系统组件 + 本地组件
        const systemWidgetList = this.remoteSystemWidgetList[group]?.[keyword] || [];
        return localWidgetList.reduce(
          (list, component) => {
            const widget = this.widgetList.find((widget) => widget.component === component);
            if (widget) list.push(widget);
            return list;
          },
          [...systemWidgetList]
        );
      },

      // 请求远程系统组件
      async getSystemWidgetList() {
        try {
          const { data } = await this.$http.querySystemWidgetList();
          const list = JSON.parse(data);
          Object.keys(list).forEach((keyword) => {
            const group = this.financeKeywordWidgetMap.get(keyword);
            if (group) {
              const widgetList = list[keyword].map((item) => {
                item.component = JSON.parse(item.component);
                return item.component;
              });
              this.$set(this.remoteSystemWidgetList.Finance, keyword, widgetList);
            }
          });
          this.remoteSystemWidgetData = list;
        } catch (error) {
          console.warn(error, '获取远程系统组件失败');
        }
      },

      onDragClone(widget) {
        const clone = deepClone(widget);
        clone.id = generateID();
        clone.label = this._generateWidgetLabel(clone);
        this.$store.state.cloneWidget = clone;
        return clone;
      },

      onDragEnter(e) {
        const component = this.$store.state.cloneWidget;
        if (!component) return;
        if (component.style.position === 'absolute') {
          const $previewer = document.querySelector('#previewer');
          const rectInfo = $previewer.getBoundingClientRect();
          const maxY = this.previewer.height - component.style.height;
          const maxX = this.previewer.width - component.style.width;
          const top = (e.clientY - rectInfo.y) / this.scaleRatio - (component.style.height / 2 || 0);
          const left =
            component.style.left || (e.clientX - rectInfo.x) / this.scaleRatio - (component.style.width / 2 || 0);
          component.style.top = top <= 0 ? 0 : top >= maxY ? maxY : top;
          component.style.left = left <= 0 ? 0 : left >= maxX ? maxX : left;
          if (component.origin) component.origin.top = component.style.top;
          if (component.origin) component.origin.left = component.style.left;
        }
        component.style.zIndex = this.zIndexMax + 1;
        this.ADD_COMPONENT(component);
      },

      // 计算组件封面
      _calcWidgetCoverImageUrl(type, widget, keyword) {
        let url = '';
        if (widget.component === 'Group') {
          url = this.remoteSystemWidgetData[keyword].find((item) => item.component.cId === widget.cId)?.url;
        } else {
          if (type === 'Finance') type = 'H5';
          url = `/admin/images/marketing/landingPage/widgets/Thumbnails/${type}/${widget.component}.png`;
        }
        return this.$staticRes(url);
      },

      // 生成不重复的组件名称
      _generateWidgetLabel(widget) {
        let index = 0;
        let label = '';
        let hasSameName = false;
        do {
          index += 1;
          label = widget.label + index;
          hasSameName = this.componentData.some((component) => component.label === label);
        } while (hasSameName);
        return label;
      }
    }
  };
</script>

<style lang="scss" scoped>
  // 组件视图
  .widget-view {
    padding-bottom: 52px;
    width: 376px;

    .widget-list {
      .widget-item {
        position: relative;
        margin-top: 24px;
        width: 156px;

        &:nth-of-type(-n + 2) {
          margin-top: 0;
        }

        .layer {
          border: 16px solid transparent;
          border-radius: 6px;
          height: 126px;
          background-color: #f8f8f8;
          transition: all 0.4s;

          .mini-pic {
            border-radius: 4px;
            max-width: 100%;
            max-height: 100%;
          }

          .super {
            position: absolute;
            top: 8px;
            right: 8px;
            border-radius: 2px;
            padding: 2px 8px;
            font-size: 12px;
            color: #fff;
            background: rgba(0, 0, 0, 0.5);
          }
        }

        &:hover {
          color: map-get($colors, 'theme');

          .layer {
            box-shadow: 0 6px 20px 1px rgba(0, 15, 97, 0.18);
          }
        }
      }

      &.basic-widget-list {
        .widget-item {
          .layer {
            border-color: #f8f8f8;
            background-color: map-get($bgColors, 'white');

            .mini-pic {
              width: 48px;
            }
          }
        }
      }
    }
  }

  // 关键字下拉菜单
  .keyword-dropdown-toggle {
    border-radius: 4px;
    padding: 12px 9px;
    min-width: 112px;
    background-color: #f8f8f8;
    user-select: none;
  }

  .keyword-dropdown-menu {
    display: flex;
    justify-content: space-between;
    border: none;
    width: 328px;
    box-shadow: 0 4px 20px 1px rgba(0, 5, 97, 0.08);

    .keyword {
      width: 56px;
      text-align: center;
      cursor: pointer;

      &:hover {
        color: map-get($colors, 'theme');
      }
    }
  }

  ::v-deep {
    .el-collapse-item__wrap {
      overflow: visible;

      .el-collapse-item__content {
        padding-bottom: 12px;
      }
    }
  }
</style>
